package pl.edu.agh.gt.real;

import java.io.File;
import java.io.IOException;
import java.util.Date;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import pl.edu.agh.gt.data.DataProvider;
import pl.edu.agh.gt.data.Rate;
import pl.edu.agh.gt.data.RatesHistory;
import pl.edu.agh.gt.ga.CrossbreedOperator;
import pl.edu.agh.gt.ga.FitnessFunction;
import pl.edu.agh.gt.ga.Individual;
import pl.edu.agh.gt.ga.Initializer;
import pl.edu.agh.gt.ga.MutationOperator;
import pl.edu.agh.gt.ga.Parameters;
import pl.edu.agh.gt.ga.Population;
import pl.edu.agh.gt.ga.PopulationListener;
import pl.edu.agh.gt.ga.PopulationStats;
import pl.edu.agh.gt.ga.greedy.CrossbreedImlpl;
import pl.edu.agh.gt.ga.greedy.FitnessFunctionImpl;
import pl.edu.agh.gt.ga.greedy.InitializerImpl;
import pl.edu.agh.gt.ga.greedy.MutationImpl;
import pl.edu.agh.gt.stock.Stock;
import pl.edu.agh.gt.stock.StockListener;
import pl.edu.agh.gt.strategy.Strategy;

public class TraderPool implements StockListener, PopulationListener {

	private final static Logger log = Logger.getLogger(TraderPool.class);

	private static final int trainingWindowSize = 48;
	private static final int trainingEvolutions = 30;
	
	RealTrader realTrader;
	//RealTrader realCounterTrader;
	
	Population population;
	Parameters params;
	Stock stock;
	RatesHistory history;

	public TraderPool(RatesHistory history) throws Exception {
		this.history = history;
		int begin = trainingWindowSize;
		int end = history.getLength();
		stock = new Stock(history.getPeriod(begin, end));
		stock.addListener(this);
		
		Strategy s = getBestStrategy();
		realTrader = new RealTrader(this, s);
	}

	private void trainPopulation() throws Exception {

		
		int iter = stock.getCurrentIteration();
		RatesHistory trainingWindow = history.getPeriod(iter, iter+trainingWindowSize);
		
		log.info("Training on window: "+trainingWindow.getFirstRate().getTime()+
				" to "+trainingWindow.getLastRate().getTime());
		
		// preare params
		params = new Parameters();
		
		FitnessFunction fitness = new FitnessFunctionImpl(trainingWindow);
		MutationOperator mutation = new MutationImpl();
		CrossbreedOperator xbreed = new CrossbreedImlpl();
		Initializer initializer = new InitializerImpl();

		// create population
		population = new Population(params, initializer, fitness, mutation, xbreed);
		population.setListener(this);

		population.initializePopulation();
		
		population.evolvePopulation(trainingEvolutions);
		
		PopulationStats stats = population.getStatistics();
		log.debug("Population evolved " + stats);
	}

	@Override
	public void onStockOpen(Stock stock, int iteration, Rate rate) {
		log.info("\n\tSTOCK OPENED " + rate.getTime() + "\t iter: " + iteration + "\t rate = " + rate);
	}

	@Override
	public void onStockClose(Stock stock, int iteration, Rate rate) throws Exception {

	}

	@Override
	public void onPopulationInitialized(Population p) throws IOException {
		p.diag();
	}

	@Override
	public void onIterationDone(Population p) {

	}

	@Override
	public void onEvolutionFinished(Population p) throws Exception {
		p.diag();
		//Individual best = p.getBestIndividual();
		//((FitnessFunctionImpl) p.getFitnessFunction()).showGenotypeTradingComparedToBuyAndHold(best.genotype);

	}
	

	public Strategy getBestStrategy() {
		
		// prepare population
		try { 
			trainPopulation();
		} catch (Exception e) {
			log.error(e);
		}

		// prepare traders
		Individual ind =  population.getBestIndividual();
		return FitnessFunctionImpl.decode(ind.genotype);
		
	}

	private void run() throws Exception {

		stock.runStock();

	}


	public static void main(String[] argv) throws Exception {


		Logger.getLogger("pl.edu.agh.gt.ga").setLevel(Level.WARN);
		Logger.getLogger("pl.edu.agh.gt.strategy").setLevel(Level.WARN);
		Logger.getLogger("pl.edu.agh.gt.stock").setLevel(Level.WARN);
		Logger.getLogger("pl.edu.agh.gt.real").setLevel(Level.DEBUG);

		// prepare history
		@SuppressWarnings("deprecation")
		Date start = new Date(2010 - 1900, 1, 15);
		@SuppressWarnings("deprecation")
		Date end = new Date(2010 - 1900, 5, 15);

		RatesHistory ratesHistory = DataProvider.readData(new File("src/main/resources/EURUSD_hour.csv"))
				.getPeriod(start, end);

		// initialize trader pool
		TraderPool pool = new TraderPool(ratesHistory);

		// launch the bastard
		pool.run();

	}


}
